using UnityEngine;
using System;

enum FFStencilValueSemantic
{
    // Dynamic object can have its own movement so in general case it can not be reprojected.
    // A value of zero is specifically assigned to this kind of object, so when using default C array
    // zero-initialization `remapTable` will be filled with "safe" values (treat all as dynamic).
    FF_STENCIL_VALUE_SEMANTIC_GENERIC_DYNAMIC_OBJECT = 0,

    // Static object has its screen motion fully determined by camera motion, so it can be
    // reprojected. Generally the best prediction quality is achieved when most parts of scene are
    // static, but incorrectly treating a moving object as static may result in noticeable flickering.
    FF_STENCIL_VALUE_SEMANTIC_STATIC_OBJECT = 1,

    // Main character is a dynamic object. It can receive special treatment in prediction algorithm.
    FF_STENCIL_VALUE_SEMANTIC_MAIN_CHARACTER = 2,

    // Reprojectible dynamic object is identified by its position in stencil remap
    // table relative to other reprojectible dynamic objects. Per-object motion
    // matrices can be passed to FF to improve prediction quality of such objects.
    FF_STENCIL_VALUE_SEMANTIC_REPROJECTIBLE_DYNAMIC_OBJECT = 3,

    // Skybox is a static object. It can receive special treatment in prediction algorithm.
    FF_STENCIL_VALUE_SEMANTIC_SKYBOX = 4,

    // This is a special value which makes FF use the application's stencil value unchanged.
    // This is intended only for tools and should not be used in most integrations.
    FF_STENCIL_VALUE_SEMANTIC_PASS_THROUGH = 5,

    FF_STENCIL_VALUE_SEMANTIC_MAX_ENUM = 0x7FFFFFFF
};

enum FFPredictionAlgorithm
{
    // Hydra algorithm.
    // Using it with extrapolation direction will result in `FF_ERROR_METHOD_NOT_SUPPORTED`.
    FF_PREDICTION_ALGORITHM_HYDRA = 0,
    // Grid-warping prediction algorithm.
    FF_PREDICTION_ALGORITHM_GRIDWARP = 1
};

enum FFResult
{
    FF_SUCCESS = 0,
    FF_COLLECTING_PREVIOUS_FRAMES = 1,
    FF_NOT_ACTIVE = 2,
    FF_ERROR_METHOD_NOT_SUPPORTED = -1,
    FF_ERROR_INSUFFICIENT_INPUT_DATA = -2,
    FF_ERROR_INCOMPATIBLE_INPUT_DATA = -3,
    FF_ERROR_CONTRADICTIVE_INPUT_DATA = -4,
    FF_ERROR_NOT_INITIALIZED = -5,
    FF_ERROR_INTERNAL_ERROR = -6,
    // FF_UPSCALING_FALLBACK_USED = 1000000,
    FF_RESULT_MAX_ENUM = 0x7FFFFFFF
};

enum FFCvvZSemantic
{
    FF_CVV_Z_SEMANTIC_MINUS_ONE_TO_ONE_FORWARD_Z = 0,
    FF_CVV_Z_SEMANTIC_ZERO_TO_ONE_REVERSE_Z = 1,
    FF_CVV_Z_SEMANTIC_MINUS_ONE_TO_ONE_REVERSE_Z = 2,
    FF_CVV_Z_SEMANTIC_ZERO_TO_ONE_FORWARD_Z = 3,
    FF_CVV_Z_SEMANTIC_MAX_ENUM = 0x7FFFFFFF
};

enum FFPerFrameDataFlagBits
{
    FF_PER_FRAME_DATA_SCENE_COLOR_BIT = 0x00000001,
    FF_PER_FRAME_DATA_DEPTH_BIT = 0x00000002,
    FF_PER_FRAME_DATA_STENCIL_BIT = 0x00000004,
    FF_PER_FRAME_DATA_VIEW_PROJ_BIT = 0x0000008,
    FF_PER_FRAME_DATA_INV_VIEW_PROJ_BIT = 0x00000010,
    FF_PER_FRAME_DATA_EXTENDED_CAMERA_INFO_BIT = 0x00000020,
    FF_PER_FRAME_DATA_OBJECT_MATRICES_BIT = 0x00000040,
    FF_PER_FRAME_DATA_FINAL_COLOR_BIT = 0x00000080,
    FF_PER_FRAME_DATA_FINAL_MASK_BIT = 0x00000100,
    FF_PER_FRAME_DATA_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
};

enum FFRenderEventId
{
    FRAME_FLOW_ACTIVATE_EVENT_ID = 776,
    FRAME_FLOW_PREDICT_EVENT_ID = 778,
    FRAME_FLOW_PROVIDE_DATA_EVENT_ID = 781
};

public enum FFStructureType
{
    FF_STRUCTURE_TYPE_DRAW_FRAME_INFO = 0,
    FF_STRUCTURE_TYPE_PREDICTION_ALGORITHM_INFO = 1,
    FF_STRUCTURE_TYPE_STENCIL_REMAP_INFO = 2,
    FF_STRUCTURE_TYPE_PER_FRAME_DATA = 3,
    FF_STRUCTURE_TYPE_CAPABILITIES_INFO = 4,
    FF_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 5,
    FF_STRUCTURE_TYPE_PER_FRAME_EXTENDED_CAMERA_INFO = 6,
    FF_STRUCTURE_TYPE_ALGORITHM_CAPABILITIES_INFO = 7,
    FF_STRUCTURE_TYPE_PER_FRAME_OBJECT_MATRICES = 8,
    FF_STRUCTURE_TYPE_RESOLUTION_INFO_2 = 9,
    FF_STRUCTURE_TYPE_PER_FRAME_FINAL_COLOR_DATA = 10,
    FF_STRUCTURE_TYPE_INSTANCE_GRAB_SUPPORT = 11,
    FF_STRUCTURE_TYPE_GRAB_INFO = 12,
    FF_STRUCTURE_TYPE_DRAW_FRAME_FLAGS_INFO = 13,
    FF_STRUCTURE_TYPE_INPUT_DESCRIPTION = 14,
    FF_STRUCTURE_TYPE_DEPTH_STENCIL_Y_DIRECTION_INVERTED = 15,
    FF_STRUCTURE_TYPE_CVV_Z_SEMANTIC_INFO = 16,
    FF_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
}

interface IFFInstance
{
    bool Init(int width, int height, FFPredictionAlgorithm algorithm, bool extrapolation);
    int SetStencilRemap(FFStencilValueSemantic[] remap);
    bool Activate();
    bool Deactivate();
    bool IsActive();
    void Feed(Matrix4x4 viewProj, IntPtr color, IntPtr depth);
    void Predict(IntPtr predict);
};